package cn.mw.cmdb.entity;

import cn.mw.cmdb.param.ImportContextParam;
import cn.mw.cmdb.param.InstanceSearchParam;
import cn.mw.cmdb.param.MwRelationPropertyType;
import cn.mw.cmdb.service.impl.CmdbServiceManage;
import cn.mw.cmdb.service.impl.CustomModelServiceImpl;
import cn.mw.cmdb.service.impl.InstanceServiceImpl;
import cn.mw.cmdb.service.impl.InstanceViewImpl;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.microMonitorCommon.entity.cmdb.ModelExportDataInfoParam;
import cn.mw.microMonitorCommon.entity.cmdb.MwImportResultParam;
import cn.mw.microMonitorCommon.util.ListMapObjUtils;
import cn.mw.microMonitorCommon.util.SpringUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.nacos.shaded.com.google.gson.Gson;
import com.google.common.base.Strings;
import com.google.gson.reflect.TypeToken;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.processor.MonitorValue.InStanceNameKey;
import static cn.mw.cmdb.service.impl.InstanceViewImpl.*;

@Slf4j
public class PropertyTypeExtMultiple extends PropertyType<PropertyTypeExtMultiple, Object> implements MwRelationPropertyType {
    public static final String ID = "extMultiple";
    private static final String FirstDropdownKey = "modelId";
    private static Map<String,List> finalList = new HashMap<>();

    private static final String SecodDropdownKey = "fieldId";


    public PropertyTypeExtMultiple() {
        setId(ID);
        setName("外部关联(多选)");
        setSortNum(5);
    }


    @Override
    public Criteria doCriteria(CriteriaOpsType opsType, String name, Object value) {
        String relationNamePath = getRelationNamePath(name, ID);
        Criteria criteria = null;
        switch (opsType) {
            case is:
                criteria = new Criteria(relationNamePath).is(value.toString());
                break;
        }
        return criteria;
    }

    @Override
    public CriteriaOpsType getDefaultCriteriaOpsType() {
        return CriteriaOpsType.is;
    }

    /**
     * 外部关联多选，前端传入json数据，需转为对象存入数据库
     *
     * @return
     */
    @Override
    public Object convertValue(Object value) {
        Gson gson = new Gson();
        List<Map<String, String>> list = new ArrayList<>();
        TypeToken<Map<String, String>> typeToken = new TypeToken<Map<String, String>>() {
        };
        if (Strings.isNullOrEmpty(strValueConvert(value))) {
            return "";
        }
        if (value instanceof List) {
            try {
                for (Object obj : (List) value) {
                    Map<String, String> map;
                    if (obj instanceof String) {
                        map = gson.fromJson(strValueConvert(obj), typeToken.getType());
                    } else {
                        map = gson.fromJson(JSON.toJSONString(obj), typeToken.getType());
                    }
                    if (map != null) {
                        Map<String, String> sortMap = sortMapByKey(map);
                        list.add(sortMap);
                    }
                }
            } catch (Exception e) {
                return "";
            }
            return list;
        }
        return null;
    }


    // 静态方法，用于创建按自定义顺序排序的 TreeMap
    public static <K, V> TreeMap<K, V> sortMapByKey(Map<K, V> map) {
        Comparator<K> comparator = new Comparator<K>() {
            @Override
            public int compare(K key1, K key2) {
                // 自定义排序规则
                if (key1.equals(relationPropertyIdKey)) return -1;
                if (key2.equals(relationPropertyIdKey)) return 1;
                if (key1.equals(relationIdKey)) return -1;
                if (key2.equals(relationIdKey)) return 1;
                if (key1.equals(relationNameKey)) return -1;
                if (key2.equals(relationNameKey)) return 1;
                return ((Comparable<K>) key1).compareTo(key2); // 其他键按字母顺序排序
            }
        };

        // 创建一个带有自定义比较器的 TreeMap 实例
        TreeMap<K, V> sortedMap = new TreeMap<>(comparator);
        sortedMap.putAll(map);
        return sortedMap;
    }


    /**
     * 获取新增字段所需要的配置数据
     *
     * @param val
     * @param context
     * @return
     */
    @Override
    public Object getDefaultInputValue(Object val, Map<String, Object> context) {
        if (context != null) {
            return context;
        }
        return null;
    }

    @Override
    public PropertyTypeExtMultiple newObj() {
        return new PropertyTypeExtMultiple();
    }

    @Override
    public Object listInputOption(PropertyTypeRef propertyTypeRef) throws Exception {
        Map<String, Object> context = propertyTypeRef.getContext();
        List<InstanceInputOption> list = new ArrayList<>();
        if (null != context) {
            CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
            InstanceServiceImpl instanceService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);
            InstanceSearchParam searchParam = new InstanceSearchParam();

            String modelId = context.get(FirstDropdownKey).toString();
            String propertyId = context.get(SecodDropdownKey).toString();

            if (StringUtils.hasText(modelId)) {
                searchParam.setModelId(modelId);
                List<InstanceInfo> instanceInfoList = instanceService.selectList(searchParam);
                if (StringUtils.hasText(propertyId) && null != instanceInfoList) {
                    for (InstanceInfo instanceInfo : instanceInfoList) {
                        InstanceInputOption inputOption = new InstanceInputOption(instanceInfo.getId(), instanceInfo.getValue(propertyId).toString());
                        list.add(inputOption);
                    }
                } else {
                    CustomModelServiceImpl customModelService = (CustomModelServiceImpl) cmdbServiceManage.getModelService(CustomModelServiceImpl.ID);
                    List<ModelInfo> modelInfos = customModelService.findAllList();
                    for (ModelInfo modelInfo : modelInfos) {
                        InstanceInputOption inputOption = new InstanceInputOption(modelInfo.getId(), modelInfo.getModelName());
                        list.add(inputOption);
                    }
                }
            }
        }

        return list;
    }


    @Override
    public boolean tableHeaderInfo(Map ms, PropertyInfo propertyInfo, List<String> labelNames, List<String> labelId) throws Exception {
        //导出表头数据时，表头字段的id和名称不能同时重复
        if ((labelId != null && !labelId.contains(propertyInfo.getId())) && (labelNames != null && !labelNames.contains(ms.get(nameKey)))) {
            ms.put(typeKey, PropertyTypeExtSingle.ID);
            Set<String> instanceNames = new HashSet<>();
            if (propertyInfo.getPropertyTypeRef() != null) {
                PropertyTypeRef propertyTypeRef = propertyInfo.getPropertyTypeRef();
                labelId.add(propertyInfo.getId());
                Map<String, Object> context = propertyTypeRef.getContext();
                CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
                InstanceViewImpl instanceView = (InstanceViewImpl) cmdbServiceManage.getModelService(InstanceViewImpl.ID);
                PropertyRelationInfo relationPropertyInfo = new PropertyRelationInfo();
                if (context != null) {
                    Object relationModelId = context.get(relationModelIdKey);
                    Object relationPropertyId = context.get(relationPropertyIdKey);
                    Object linkPropertyId = context.get(linkPropertyIdKey);
                    Object linkTargetPropertyId = context.get(linkTargetPropertyIdKey);
                    relationPropertyInfo.setRelationModelId(strValueConvert(relationModelId));
                    relationPropertyInfo.setRelationPropertyId(strValueConvert(relationPropertyId));
                    relationPropertyInfo.setLinkPropertyId(strValueConvert(linkPropertyId));
                    relationPropertyInfo.setLinkTargetPropertyId(strValueConvert(linkTargetPropertyId));
                }

                List<MwRelationInstanceParam> selectDataByRelation = instanceView.getSelectDataByRelation(relationPropertyInfo);
                Set<String> selectDataList = new HashSet<>();
                List<MwRelationInstanceParam> linkDataList = new ArrayList<>();
                for (MwRelationInstanceParam mwRelationInstanceParam : selectDataByRelation) {
                    if (!Strings.isNullOrEmpty(mwRelationInstanceParam.getRelationName()) && !Strings.isNullOrEmpty(mwRelationInstanceParam.getRelationId())) {
                        selectDataList.add(mwRelationInstanceParam.getRelationName());
                        if (StringUtils.hasText(mwRelationInstanceParam.getLinkPropertyName())) {
                            mwRelationInstanceParam.setLinkTargetPropertyId(relationPropertyInfo.getLinkTargetPropertyId());
                            linkDataList.add(mwRelationInstanceParam);
                        }
                    }
                }

                ms.put(selectDataKey, new ArrayList<>(selectDataList));
                if (!linkDataList.isEmpty()) {
                    ms.put(linkDataKey, linkDataList);
                }
                return true;
            }
        }
        return false;
    }

    /**
     * 外部关联多选，从数据库中获取数据装成前端需要的json数据
     *
     * @param val
     * @return
     */
    @Override
    public Object readValue(Object val, Map<String, Object> context) {
        List list = new ArrayList();
        if (val != null && val instanceof List) {
            for (Object obj : (List) val) {
                if (obj != null && obj instanceof Map) {
                    String jsonString = JSONObject.toJSONString(obj);
                    list.add(jsonString);
                }

            }
            return list;
        }
        return null;
    }


    @Override
    public Object lookValue(Object val, Map<String, Object> context) {
        return readValue(val, context);
    }

    /**
     * 导出数据转换
     *
     * @param val
     * @param context
     * @return
     */
    @Override
//    @Override
    public Object exportValue(Object val, Map<String, Object> context) {
        String str = "";
        Set<String> list = new HashSet<>();
        if (val != null && val instanceof List) {
            for (Object obj : (List) val) {
                Map map = (Map) obj;
                String relationName = strValueConvert(map.get(relationNameKey));
                list.add(relationName);
            }
        }
        if (!CollectionUtils.isEmpty(list)) {
            str = String.join(",", list);
        }
        return str;
    }

    @Override
    public Object tableHeaderTipInfo(PropertyTypeRef propertyTypeRef) {
        return "多个数据用“,”隔开";
    }

    /**
     * 获取实例数据中外部关联多选的匹配字段
     *
     * @param key
     * @param val
     * @param instanceId
     * @return
     */
    @Override
    public Map<String, Object> getRelationFieldId(String key, Object val, String instanceId, String replace) {
        Map ms = new HashMap();
        boolean isFlag = false;
        if (val instanceof List) {
            List extSingleList = (List) val;
            for (Object obj : extSingleList) {
                if (obj instanceof Map) {
                    Map mapInfo = (Map) obj;
                    Object relationId = mapInfo.get(relationIdKey);
                    if (instanceId.equals(relationId)) {
                        isFlag = true;
                        mapInfo.put(relationNameKey, replace);
                    }
                }
            }
            if (isFlag) {
                ms.put(key, val);
            }
        }
        return ms;
    }

    @Override
    public Object getRelationName(String key, Object val, String instanceId) {
        if (val instanceof List) {
            List extSingleList = (List) val;
            for (Object obj : extSingleList) {
                if (obj instanceof Map) {
                    Map mapInfo = (Map) obj;
                    Object relationId = mapInfo.get(relationIdKey);
                    if (instanceId.equals(relationId)) {
                        return mapInfo.get(relationNameKey);
                    }
                }
            }
        }
        return null;
    }

    @Override
    public void refresh() {
        finalList.clear();
    }

    @Override
    public Object getDataValue(ImportContextParam contextParam) throws Exception {
        CmdbServiceManage cmdbServiceManage = SpringUtils.getBean(CmdbServiceManage.class);
        InstanceServiceImpl modelService = (InstanceServiceImpl) cmdbServiceManage.getModelService(InstanceServiceImpl.ID);

        MwImportResultParam resultParam = new MwImportResultParam();
        ModelExportDataInfoParam importParam = contextParam.getParam();
        //属性id
        String relationModelId = importParam.getRelationModelId();

        String message = "";
        //属性名称
        String tableName = importParam.getTableName();
        Object cellValue = importParam.getCellValue();
        Map<String, Object> matchMap = new HashMap<>();
        importCheckInfo(resultParam, contextParam, matchMap);

        log.info(tableName + ":extMultiple::" + cellValue);
        List<InstanceInfo> instanceInfoList = new ArrayList<>();
        if (finalList==null || finalList.size()==0) {
            instanceInfoList = modelService.doListByModelIdsNotAuth(Arrays.asList(relationModelId));
            finalList.put(relationModelId,instanceInfoList);
        }else{
            instanceInfoList = finalList.get(relationModelId);
        }
        Map<String, String> instanceNameById = instanceInfoList.stream().filter(s -> !Strings.isNullOrEmpty(strValueConvert(s.getData().get(InStanceNameKey)))).collect(Collectors.toMap(s -> strValueConvert(s.getData().get(InStanceNameKey)), s -> s.getId(), (
                value1, value2) -> {
            return value2;
        }));

        String cellValStr = strValueConvert(cellValue);
        String[] splits = cellValStr.split(",");
        List<MwRelationInstanceParam> list = new ArrayList<>();
        if (!Strings.isNullOrEmpty(cellValStr)) {
            for (String cellVal : splits) {
                MwRelationInstanceParam relationParam = new MwRelationInstanceParam();
                if (instanceNameById != null && instanceNameById.containsKey(cellVal)) {
                    String relationId = instanceNameById.get(cellVal);
                    relationParam.setRelationId(relationId);
                    relationParam.setRelationPropertyId(mwInstanceNameKey);
                    relationParam.setRelationName(cellVal);
                } else {
                    message += tableName + ":" + cellValue + "不存在";
                }
                list.add(relationParam);
            }
        }
        List<Map> mapList = ListMapObjUtils.objectsToMaps(list);
        resultParam.setCellValue(mapList);
        resultParam.setMessage(message);
        return resultParam;
    }

}
